﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NSEngine;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;

namespace OOSync
{
    public interface IDirtyDataLink
    {
        void Return(string nm);
    }
    /*
    public class TcpDirtyDataLink : DirtyDataLink
    {
        public TcpDirtyDataLink(Session session)
        {
            m_session = session;
        }
        public void Return(QK_JsonValue_Map nm)
        {
            Node.Single.Notify(m_session,nm.ToString());
        }
        public uint GetSID() { return m_session.GetSID(); }
        public string GetUID() { return m_session.GetUID().ToString(); }

        Session m_session;
    }
    */
    /// <summary>
    /// 脏数据分发器
    /// </summary>
    public class DirtyDataDispatcher
    {
        public DirtyDataDispatcher()
        {
            mRootObj = new SyncObj_Server(this);
        }

        public void SetDirtyDataLink(IDirtyDataLink link)
        {
            mDrityDataLink = link;
        }

        /// <summary>
        /// 手动发送同步命令
        /// </summary>
        internal void ManualSync()
        {
            if (m_ChangedObjs.Count < 1) return  ;

            //生成更新封包
            var nm = new JObject();
            {
                nm["n"] = "_Sync";//增加包头
                nm["sid"] = Application.sid.ToString();
                nm["tm"] = DateTime.Now.ToFileTime();//加入服务器当前时间戳
                var paths = new JObject();

                //按对象路径索引
                Dictionary<string, List<SyncObj_Server>> SyncList = new Dictionary<string, List<SyncObj_Server>>();
                foreach (var kv in m_ChangedObjs)
                {
                    SyncObj_Server curr = kv.Value;
                    var path = (curr.RemovePath != null) ? curr.RemovePath : curr.Parent.Path;
                    if (!SyncList.ContainsKey(path)) SyncList.Add(path, new List<SyncObj_Server>());
                    SyncList[path].Add(curr);
                }

                //同步对象
                foreach (var kv in SyncList)
                {
                    string path = kv.Key;
                    var objs = new JArray();
                    foreach (var curr in kv.Value)
                    {
                        objs.Add( curr.Serialize());
                        curr.CleanDirty();
                    }
                    paths[path] = objs;
                }


                nm["o"] = paths;
                m_ChangedObjs.Clear();//清除变更记录
            }
            if(mDrityDataLink!=null) mDrityDataLink.Return(nm.ToString()); 
        }

        /*
        internal List<LJsonValue_Map> FirstLoginSync()
        {
            if (m_ChangedObjs.Count < 1) return null;
            var relist = new List<LJsonValue_Map>();
            //按对象路径索引
            Dictionary<string, List<SyncObj_Server>> SyncList = new Dictionary<string, List<SyncObj_Server>>();
            foreach (var kv in m_ChangedObjs)
            {
                SyncObj_Server curr = kv.Value;
                var path = (curr.RemovePath != null) ? curr.RemovePath : curr.Parent.Path;
                if (!SyncList.ContainsKey(path)) SyncList.Add(path, new List<SyncObj_Server>());
                SyncList[path].Add(curr);
            }
            int flagindex = GamePublic.syncNum > 0 ? GamePublic.syncNum : 1;
            int count = SyncList.Count;
            int Round = 1;
            if (count / flagindex > 0)
            {
                Round = count / flagindex + 1;
            }
            while (Round > 0)
            {
                string[] keys = SyncList.Keys.ToArray<string>();
                //生成更新封包
                var nm = new LJsonValue_Map();
                {
                    nm.addStrValue("n", "_Sync");//增加包头
                    nm.addStrValue("sid", Application.sid.ToString());
                    nm.addStrValue("tm", DateTime.Now.ToFileTime().ToString());//加入服务器当前时间戳
                    var paths = new LJsonValue_Array();
                    //同步对象(三个一切分)
                    int index = 0;
                    foreach (string k in keys)
                    {
                        index++;
                        string path = k;
                        List<SyncObj_Server> templist = SyncList[k];
                        var objs = new LJsonValue_Array();
                        foreach (var curr in templist)
                        {
                            objs.addValue("", curr.Serialize());
                            curr.CleanDirty();
                        }
                        paths.addValue(path, objs);
                        SyncList.Remove(k);
                        //Node.Single.LogOut(LOG_TYPE.LT_WARNING, k);
                        if (index >= flagindex)
                            break;
                    }
                    nm.addValue("o", paths);
                }
                Round--;
                relist.Add(nm);
            }
            m_ChangedObjs.Clear();//清除变更记录


            //mDrityDataLink.Return(nm);
            return relist;
        }*/

        internal void SetChanged(SyncObj_Server obj)
        {
            string path;
            if (obj.RemovePath == null)//一个没有被删除的对象
                path = obj.Path;
            else//当前对象是一个已经被删除的对象 
                path = obj.RemovePath == "" ? obj.Name : obj.RemovePath + "/" + obj.Name;


            if (m_ChangedObjs.ContainsKey(path))
                m_ChangedObjs[path] = obj;
            else
                m_ChangedObjs.Add(path, obj);

            //m_isChange = true;
            DispatcherManager.Single.SetChanged(this);
        }

        //public bool IsChange { get { return m_isChange; } }

        internal SyncObj_Server RootObj { get { return mRootObj; } }

        //bool m_isChange = false;
        SyncObj_Server mRootObj;
        IDirtyDataLink mDrityDataLink;
        Dictionary<string, SyncObj_Server> m_ChangedObjs = new Dictionary<string, SyncObj_Server>();
    }
}
